<?php
class Document {
	/**
	* @var mixed Mysql connection
	*/
	var $mysqli = null;
	/**
	* @var array User credentials (id, email, type)
	*/
	var $user = null;
	/**
	* @var array Notifications
	*/
	var $notif = array();
	/**
	* @var string Area of concentration
	*/
	var $area = 'doc';
	/**
	* @var string Database table to be used
	*/
	var $table = 'Documents';
	/**
	* @var mixed Options
	*/
	var $opts = null;
	/**
	* @var string Path to document
	*/
	var $path = "data/doc/";
	/**
	* @var string Source of document
	*/
	var $srcid = null;
	
	/**
	* Document constructor
	* Initializes document variables for intended request
	* 
	* @param string $area Area of concentration
	* @param array $opts Additional data
	* @param resource $mysqli Current mysql connection
	* @param resource $user User credentials (id, email, type)
	*/
	function __construct($area, $opts, $mysqli, $user) {
		# Include all necessary classes
		require_once "class/setting.php";
		require_once "class/file.php";
		require_once "class/resource.php";
		require_once "class/location.php";
		require_once "class/microorganism.php";
		require_once "class/section.php";
		require_once "class/project.php";
		require_once "class/tool.php";
		
		$this->mysqli = $mysqli;
		$this->user = $user;
		$this->area = $area;
		
		# Decide on area
		switch($area) {
			# Microorganism
			case 'micro':
				$this->table = 'MicroDocs';
				$this->path = "data/micro/{$opts['id']}/doc/";
				$this->srcid = $opts['id'];
			break;
			
			# Project
			case 'proj':
				$this->table = 'ProjDocs';
				$this->path = "data/proj/{$opts['id']}/doc/";
				$this->srcid = $opts['id'];
			break;
			
			# Location
			case 'loc':
				$this->table = 'LocDocs';
				$this->path = "data/loc/{$opts['id']}/doc/";
				$this->srcid = $opts['id'];
			break;
			
			# Resource
			case 'rsrc':
				$this->table = 'RsrcDocs';
				$this->path = "data/rsrc/{$opts['id']}/doc/";
				$this->srcid = $opts['id'];
			break;
			
			# Project section
			case 'proj-sec':
				$this->table = 'ProjSecDocs';
			break;
			
			# Section
			case 'sec':
				$this->path = "data/{$opts['sec']}/{$opts['pid']}/sec/{$opts['sid']}/doc/";
				$this->srcid = $opts['sid'];
			break;
			
			default:
				$this->path = "data/doc/";
				$this->area = 'doc';
			break;
		}
	}
	
	/**
	* Search document
	* Searches for a document based on
	* query string, optional paramaters as constraints,
	* start and end line of result in a mysql resource
	* 
	* @access public
	* @param string $query Keyword/s to look for in the database
	* @param array $opts Contains constraints in search (category, order, author, etc.)
	* @param integer $start Beginning line of searched keyword in mysql resource
	* @param integer $limit End of returned mysql resource as a result of search
	* 
	* @return array Mixed result from mysql query and size of returned rows
	*/
	public function search($query, $opts, $start, $limit) {
		$query = is_array($query) ? $query : Tool::trimout($query);
		$selSize = "SELECT FOUND_ROWS()";
		
		# Via document ID
		if($opts["c"]=="id" or $opts["c"]=="view") {
			$query = empty($opts['id']) ? $query : $opts['id'];
			
			$sel = "
				SELECT SQL_CALC_FOUND_ROWS DISTINCT T1.* FROM Documents AS T1 WHERE T1.ID='{$query}' ".(in_array($this->user['type'], array('ADMIN','PRIME')) ? '' : "AND T1.Remove='0'")."
					AND ('{$this->user['type']}'='PRIME' OR T1.Visib='PUB' OR (T1.Visib='PRV' AND (T1.CrtBy='{$this->user['id']}'
					OR (SELECT COUNT(*) FROM DocCoeds AS T2 WHERE T2.PID='{$query}' AND T2.CID='{$this->user['id']}') > 0)))
				ORDER BY T1.Title
			";
		}
		else {
			$cond = "";
			
			# Other category
			switch($opts["c"]) {
				# Document name
				case "name":
					$categ = " WHERE T1.Name LIKE '%{$query}%' ";
				break;
				
				# Project
				case "proj":
					$categ = "
						INNER JOIN ProjDocs AS T3 INNER JOIN Projects AS T4
							ON T1.ID=T3.CID AND T3.PID=T4.ID
						WHERE T4.Title LIKE '%{$query}%' OR T4.Abstr LIKE '%{$query}%'
					";
				break;
				
				# Microorganism
				case "micro":
					$categ = "
						INNER JOIN MicroDocs AS T3 INNER JOIN Microorganisms AS T4
							ON T1.ID=T3.CID AND T3.PID=T4.ID
						WHERE T4.Name LIKE '%{$query}%' OR T4.Notes LIKE '%{$query}%'
					";
				break;
				
				# Mutiple documents
				case "multi-id":
					$categ = "WHERE T1.ID IN ('".implode("','", $query)."')";
				break;
				
				# Exact title
				case 'exact':
					$categ = "WHERE T1.Title='{$query}'";
				break;
				
				# Any occurrence in title
				case 'title':
					$categ = "WHERE T1.Title LIKE '%{$query}%'";
				break;
			}
			
			# Break down query string to pieces
			if(!is_array($query)) $arrQuery = explode(" ", Tool::trimout($query));
			
			# Ordering
			$opts["ob"] = isset($opts["ob"]) ? $opts['ob'] : "Title";
			$opts["oa"] = isset($opts["oa"]) ? $opts["oa"] : "ASC";
			
			# Included words/phrases
			if(!empty($opts["i"])) {
				$cond .= " (T1.Title LIKE '%{$opts["i"]}%' OR T1.Abstr LIKE '%{$opts["i"]}%') AND ";
			}
			
			# Excluded words/phrase
			if(!empty($opts["e"])) {
				$arrQuery = explode(", ", $opts["e"]);
				$title = " T1.Title NOT LIKE '%".implode("%' OR T1.Title NOT LIKE '%", $arrQuery)."%'";
				$abstr = " T1.Abstr NOT LIKE '%".implode("%' OR T1.Abstr NOT LIKE '%", $arrQuery)."%'";
				$cond .= " ({$title} AND {$abstr}) AND ";
			}
			
			# Creator
			if(!empty($opts["cb"])) {
				if(empty($opts['cbi'])) {
					$name = explode(", ", $opts["cb"]);
					
					# Last name, first name, mid name
					if(count($name)==3) {
						list($lname, $fname, $mi) = $name;
						$cond .= " (T1.CrtBy IN (SELECT ID FROM Accounts WHERE Lname='".Tool::trimout($lname)."'AND Fname='".Tool::trimout($fname)."') AND ";
					}
					# Email
					else if(strrpos($opts['cb'], '@') > 1) {
						$cond .= " (T1.CrtBy IN (SELECT ID FROM Accounts WHERE Email='{$opts['cb']}')) AND ";
					}
					# Other
					else {
						$cond .= "(T1.CrtBy='%{$query}%') AND ";
					}
				}
				# Account ID
				else {
					$cond .= " (T1.CrtBy='{$opts['cbi']}') AND ";
				}
			}
			
			# Creation date
			if(!empty($opts['co']['s'])) {
				# Date range
				if(!empty($opts["co"]["e"])) {
					$cond .= " (T1.CrtOn BETWEEN '".Tool::trimout($opts["co"]["s"])."' AND '".Tool::trimout($opts["co"]["e"])."') AND ";
				}
				# Exact date
				else {
					$cond .= " (T1.CrtOn='".Tool::trimout($opts["co"]["s"])."') AND ";
				}
			}
			
			# Title
			if(empty($opts["c"]) or ($opts["c"]=="title" and !empty($query))) {
				$cond .= " (T1.Title LIKE '%{$query}%') AND ";
			}
			
			# Removed items
			$cond .= (in_array($this->user['type'], array('ADMIN','PRIME')) and $opts['c']=='remove') ? " T1.Remove='1' AND " : " T1.Remove='0' AND ";
			
			# Limit of returned rows
			$range = (isset($start) and !empty($limit)) ? "LIMIT {$start}, {$limit}" : '';
			
			# Additional category
			if(empty($categ)) {
				$cond = "
					WHERE {$cond} (T1.Visib='PUB' OR ('{$this->user['type']}'='PRIME')
						OR (T1.Visib='PRV' AND (T1.CrtBy='{$this->user['id']}'
						OR (SELECT COUNT(T2.CID) FROM ImgCoeds AS T2 WHERE T2.PID=T1.ID AND T2.CID='{$this->user['id']}') > 0)))
				";
			}
			else {
				$cond = "
					{$categ} AND {$cond} (T1.Visib='PUB' OR ('{$this->user['type']}'='PRIME')
						OR (T1.Visib='PRV' AND (T1.CrtBy='{$this->user['id']}'
						OR (SELECT COUNT(T2.CID) FROM ImgCoeds AS T2 WHERE T2.PID=T1.ID AND T2.CID='{$this->user['id']}') > 0)))
				";
			}
			
			# Search string
			$sel = "
				SELECT SQL_CALC_FOUND_ROWS DISTINCT T1.* FROM Documents AS T1 {$cond} ORDER BY T1.{$opts["ob"]} {$opts["oa"]} {$range}
			";
		}
		
		# Search in database
		$res = $this->mysqli->query($sel);
		$size = $this->mysqli->query($selSize);
		$size = $size->fetch_row();
		
		# Return searched rows and size of rows
		return array($res, $size[0]);
	} # function document
	
	/**
	* Create document
	* Create a new document
	* 
	* @access public
	* @param mixed $doc Document
	* @param string $title Title
	* @param string $notes Additional information
	* @param string $link External link to document
	* @param array $micros Microorganisms
	* @param array $projs Projects
	* @param array $locs Locations
	* @param array $coeds Coeditors
	* @param string $categ Category
	* @param string $visib Visibility
	* 
	* @return mixed ID on success, false on failure
	*/
	public function create($doc, $title, $abstr, $ref, $micros, $projs, $locs, $coeds, $categ, $visib) {
		$id = Tool::generateID($this->area);
		
		$path = $this->path.$id.'/';
		$name = Tool::trimout($doc['name']);
		$abstr = Tool::trimout($abstr);
		
		# Directory of document
		if(!is_dir($path)) {
			if(!mkdir($path, 0777, true)) {
				echo 'ERROR: make ftp doc dir';
				return false;
			}
		}
		
		# New filename
		$filename = str_replace(' ', '_', substr($name, 0, -4)).'-'.uniqid().'.pdf';
		$filepath = $path.$filename;
		
		# Upload or copy document
		if((is_uploaded_file($doc['tmp_name']) and move_uploaded_file($doc['tmp_name'], $filepath))
			or (file_exists($doc['tmp_name']) and rename($doc['tmp_name'], $filepath))
		) {
			$ins = "
				INSERT INTO Documents VALUES (
					'{$id}', '{$categ}', '{$visib}',
					'".mysql_real_escape_string(empty($title) ? $doc['name'] : $title)."',
					".(empty($abstr) ? 'NULL' : "'".mysql_real_escape_string($abstr)."'").",
					".(empty($ref) ? 'NULL' : "'".mysql_real_escape_string($ref)."'").",
					".(empty($filename) ? 'NULL' : "'".mysql_real_escape_string($filename)."'").",
					".(empty($doc['type']) ? 'NULL' : "'".mysql_real_escape_string($doc['type'])."'").",
					".(empty($doc['size']) ? 'NULL' : "'".mysql_real_escape_string($doc['size'])."'").",
					".(empty($filepath) ? 'NULL' : "'".mysql_real_escape_string($filepath)."'").",
					'{$this->area}', ".(empty($this->srcid) ? 'NULL' : "'".$this->srcid."'").",
					".(empty($coeds["val"]) ? 0 : count($coeds["val"])).",
					NULL, NULL, 0, NULL, NULL, 0, '{$this->user['id']}', '".date('Y-m-d H:i:s:ms')."', '0'
				)
			";
			
			# Insert document details to database
			if($this->mysqli->query($ins)) {
				# Append microorganisms
				if(!empty($micros['val'])) {
					$micro = new Microorganism('doc', $this->mysqli, $this->user);
					$micro->append($micros, $id, true);
				}
				
				# Append projects
				if(!empty($projs['val'])) {
					$proj = new Project('doc', $this->mysqli, $this->user);
					$proj->append($projs, $id);
				}
				
				# Append locations
				if(!empty($locs['val']) or !empty($locs['coord'])) {
					//to-do
					// $loc = new Location('img', $this->mysqli, $this->user);
					// $loc->append($locs, $id, array('categ'=>$categ, 'visib'=>$visib));
				}
				
				# Append coeditors
				if(!empty($coeds['val'])) {
					$edtr = new Editor('doc', $this->mysqli, $this->user);
					$edtr->append($coeds, $id, false);
				}
			}
			# Error inserting document
			else {
				$this->notif[] = "ERROR: ins doc";
			}
		}
		# Error moving/copying document
		else {
			$this->notif[] = "ERROR: ftp put doc 2";
		}
		
		# Successfully created document
		if(empty($this->notif)) {
			return $id;
		}
		
		//echo '<pre>', var_dump($this->notif), '</pre>';
		return false;
	}
	
	/**
	* Update document
	* Update an existing document on the system
	* 
	* @access public
	* @param string $id Document ID
	* @param string $title Title
	* @param string $notes Additional information
	* @param array $micros Microorganisms
	* @param array $rsrcs Resources
	* @param array $coeds Coeditors
	* @param string $categ Category
	* @param string $visib Visibility
	* @param array $rmicros Microorganisms to be removed
	* @param array $rrsrcs Resources to be removed
	* @param array $rcoeds Coeditors to be removed
	* 
	* @return boolean True on success, false on failure
	*/
	public function update(
		$id, $title, $abstr, $ref, $micros, $rsrcs, $coeds, $categ, $visib, $rmicros, $rrsrcs, $rcoeds
	) {
		$upd = "
			UPDATE Documents SET
				Title='{$title}', Abstr='{$abstr}', Ref='{$ref}', Categ='{$categ}', Visib='{$visib}',
				UpdBy='{$this->user['id']}', UpdOn='".date('Y-m-d H:i:s:ms')."', UpdNo=UpdNo+1
			WHERE ID='{$id}'
		";
		
		# Update document
		if($this->mysqli->query($upd)) {
			# Operate on microorganisms to be added/removed
			$micro = new Microorganism('doc', $this->mysqli, $this->user);
			$micro->operate($micros, $rmicros, $id, false);
			
			# Operate on resources to be added/removed
			$rsrc = new Resource('doc', $this->mysqli, $this->user);
			$rsrc->operate($rsrcs, $rrsrcs, $id);
			
			# Operate on coeditors to be added/removed
			$coed = new Editor('doc', $this->mysqli, $this->user);
			$coed->operate($coeds, $rcoeds, $id, false);
		}
		# Error in updating document
		else {
			$this->notif[] = "Error in updating details of document {$title}.<br/>";
		}
		
		# Successfully updated document
		if(empty($this->notif)) {
			return true;
		}
		
		//echo '<pre>', var_dump($this->notif), '</pre>';
		return false;
	}
	
	/**
	* Delete document
	* Delete an existing document from the system
	* 
	* @access public
	* @param string $id Document ID
	* @param string $path Path to document
	* 
	* @return boolean True on success, false on failure
	*/
	public function delete($id) {
		$del = "UPDATE Documents SET Remove='1' WHERE ID='{$id}'";
		
		# Remove from database
		if($this->mysqli->query($del)) {
			return true;
		}
		
		# Error on deletion
		echo 'ERROR: del doc';
		return false;
	}
	
	/**
	* Recover document
	* Recover a deleted document
	* 
	* @access public
	* @param string $id Document ID
	* 
	* @return boolean true on success, false on failure
	*/
	public function recover($id) {
		# Query string to recover document
		$del = "UPDATE Documents SET Remove='0' WHERE ID='{$id}'";
		
		# Recover document in the database
		$res = $this->mysqli->query($del);
		
		# Error occurred in deletion
		if(!$res) {
			echo "ERROR: recover";
			return false;
		}
		
		# Successfully recovered document
		return true;
	} # function recover
	
	/**
	* Upload JSON input for document 
	* Upload json input of documents to be added or updated
	* 
	* @access public
	* @param mixed $inputs JSON inputs
	* @param string $action Action to be performed on uploaded inputs
	* @param mixed $opts Additional parameters
	* 
	* @return array Results on each input processed
	*/
	public function upload($inputs, $action, $opts) {
		$results = array();
		$error = array();
		
		# Scan each json file
		foreach($inputs['tmp_name'] as $i => $path) {
			# Temporary file and directory
			$inpath = 'data/tmp/'.$this->user['id'].'-'.uniqid();
			$input = $inpath.'/'.Tool::trimout($inputs['name'][$i], 25);
			
			# Make temporary directory and move file
			if(!mkdir($inpath, 0777, true)) {
				continue;
			}
			
			if(is_uploaded_file($path)) {
				if(!move_uploaded_file($path, $input)) {
					continue;
				}
			}
			else if(!file_exists($path) or !rename($path, $input)) {
				rmdir($inpath); echo 'ERROR!!!<br/>';
				continue;
			}
			
			# Decode json contents
			$json = json_decode(utf8_encode(preg_replace( '/\s+/', ' ', file_get_contents($input))));
			
			# Path or file is not found
			if(!$json or empty($json->filepath)) {
				$results[$i] = false;
				$results['error'][] = $inputs['name'][$i];
				# Remove temp json file
				unlink($input);
				rmdir($inpath);
				continue;
			}
			
			# Path to document
			if(file_exists($json->filepath)) {
				$filepath = $json->filepath;
			}
			elseif(!empty($inputs['path'][$i]) and file_exists($inputs['path'][$i].'/'.$json->filepath)) {
				$filepath = $inputs['path'][$i].'/'.$json->filepath;
			}
			else {
				$results[$i] = false;
				$results['error'][] = $inputs['name'][$i];
				# Delete json input
				unlink($input);
				rmdir($inpath);
				continue;
			}
			
			# Title, Abstract, Reference, Path
			$title = empty($json->title) ? null : $json->title;
			$abstr = empty($json->abstract) ? null : $json->abstract;
			$ref = empty($json->references) ? null : $json->references;
			
			# Authors
			$authors = array();
			if(!empty($json->authors)) {
				foreach($json->authors as $auth) {
					$authors['val'][] = empty($auth->email) ? implode(',', array($auth->name[0], $auth->name[1], $auth->name[2])) : $auth->email;
					$authors['id'][] = empty($auth->id) ? null : $auth->id;
				}
			}
			
			# Microorganisms
			$micros = array();
			if(!empty($json->microorganisms)) {
				foreach($json->microorganisms as $micro) {
					if(!empty($micro->name)) {
						$micros['val'][] = $micro->name;
						$micros['code'][] = empty($micro->code) ? null : $micro->code;
						$micros['auth'][] = empty($micro->authors) ? null : $micro->authors;
						$micros['note'][] = empty($micro->notes) ? null : $micro->notes;
						$micros['id'] = empty($micro->id) ? null : $micro->id;
					}
				}
			}
			
			# Projects
			$projs = array();
			if(!empty($json->projects)) {
				foreach($json->projects as $proj) {
					if(!empty($proj->title)) {
						$projs['val'][] = $proj->title;
						$projs['abstr'][] = empty($proj->abstract) ? null : $proj->abstract;
						$projs['id'] = empty($proj->id) ? null : $proj->id;
					}
				}
			}
			
			# Locations
			$locs = array();
			if(!empty($json->locations)) {
				foreach($json->locations as $loc) {
					if(!empty($loc->name)) {
						$locs['val'][] = $loc->name;
						$locs['coord'][] = (empty($loc->coords[0]) or empty($loc->coords[1])) ? null : array($loc->coords[0], $loc->coords[1]);
						$locs['id'][] = empty($loc->id) ? null : $loc->id;
					}
				}
			}
			
			# Resources
			$rsrcs = array();
			if(!empty($json->resources)) {
				foreach($json->resources as $rsrc) {
					$rsrcs['title'][] = empty($rsrc->title) ? null : $rsrc->title;
					$rsrcs['notes'][] = empty($rsrc->notes) ? null : $rsrc->notes;
					$rsrcs['links'][] = empty($rsrc->links) ? null : $rsrc->links;
					$rsrcs['id'][] = empty($rsrc->id) ? null : $rsrc->id;
				}
			}
			
			# Sources
			$srces = array();
			if(!empty($json->sources)) {
				foreach($json->sources as $srce) {
					$srces['journ'][] = empty($srce->journal) ? null : $srce->journal;
					$srces['year'][] = empty($srce->year) ? null : $srce->year;
					$srces['vol'][] = empty($srce->volume) ? null : $srce->volume;
					$srces['num'][] = empty($srce->number) ? null : $srce->number;
					$srces['page'][] = empty($srce->page) ? null : $srce->page;
				}
			}
			
			# Settings
			$coeds = array();
			$categ = 'ADV';
			$visib = 'PRV';
			if(!empty($json->settings)) {
				$st = $json->settings;
				
				# Coeditors
				if(!empty($st->coeditors)) {
					foreach($st->coeditors as $coed) {
						$coeds['val'][] = empty($coed->email) ? $coed->name : $coed->email;
						$coeds['id'][] = empty($coed->id) ? '' : $coed->id;
					}
				}
				
				# Category
				if(!empty($st->category)) {
					switch(strtolower($st->category)) {
						case 'advanced':
						case 'adv':
							$categ = 'ADV';
						break;
						
						case 'basic':
						case 'bsc':
							$categ = 'BSC';
						break;
					}
				}
				
				# Visibility
				if(!empty($st->visibility)) {
					switch(strtolower($st->visibility)) {
						case 'private':
						case 'prv':
							$visib = 'PRV';
						break;
						
						case 'public':
						case 'pub':
							$visib = 'PUB';
						break;
					}
				}
			}
			
			# Action to be performed
			switch($action) {
				# Create document
				case 'make':
					$file = pathinfo($filepath);
					
					# Cread document
					$results[$i] = $id = $this->create(
						array (
							'name'=>$file['basename'], 'type'=>'application/pdf',
							'tmp_name'=>$filepath, 'error'=>0, 'size'=>filesize($filepath)
						), $title, $abstr, $ref, $micros, $projs, $locs, $coeds, $categ, $visib
					);
				break;
				
				# Update document
				case 'edit':
					# Find document if ID is missing
					if(empty($opts['id'])) {
						list($res, $size) = $this->search($opts['id'], array('c'=>'id'), 0, 10);
						# Document found
						if(!empty($size)) {
							$img = $res->fetch_object();
							$opts['id'] = $img->ID;
						}
					}
					
					# Update document
					if(!empty($opts['id'])) {
						$results[$i] = $this->update(
							$opts['id'], $title, $abstr, $micros, $rsrcs, $coeds, $categ, $visib, null, null, null
						);
					}
				break;
			}
			
			# Error occurred
			if($results[$i]===false) {
				$results['error'][] = $inputs['name'][$i];
			}
			
			# Remove json file and directory
			unlink($input);
			rmdir($inpath);
		}
		
		# Return all results
		return $results;
	}
	
	/**
	* Download document
	* Download all allowed details of an document
	* 
	* @access public
	* @param string $id Document ID
	*/
	public function download($id) {
		# Search image
		list($res, $size) = $this->search($id, array('c'=>'id'), null, null);
		
		# Image not found
		if(empty($size)) {
			header('refresh: 0.1; url="http://localhost/microwebph/main.php?doc=view&fail=get&id='.$id.'"'); return false;
		}
		
		# Get document
		$doc = $res->fetch_object();
		
		# Document does not exist
		if(!file_exists($doc->Path)) {
			header('refresh: 0.1; url="http://localhost/microwebph/main.php?doc=view&fail=get&id='.$id.'"'); return false;
		}
		
		# Get document's settings
		$sett = new Setting('doc', null, $this->mysqli, $this->user);
		$cond = '';
		
		# Basic
		if($doc->Categ=='BSC') {
			$cond = "AND T1.Categ='BSC' AND T1.Visib='PUB'";
		}
		# Permitted users
		else if(!$sett->verify($id)) {
			header('refresh: 0.1; url="http://localhost/microwebph/main.php?doc=view&fail=get&id='.$id.'"'); return;
		}
		
		# Download as PDF document
		header('Content-disposition: attachment; filename=[microwebph] '.$doc->Title.'.pdf');
		header('Content-type: application/pdf');
		ob_clean();
		flush();
		readfile($doc->Path);
	}
	
	/**
	* Process appended and remove documents
	* Process on all documents associated with an area
	* which are to be appended or removed
	* 
	* @access public
	* @param array $addl Documents to be appended
	* @param array $rmvl Documents to be removed
	* @param string $id ID of area
	* @param boolean $new Documents to be appended, if non-existent, must be created
	*/
	public function operate($addl, $rmvl, $id) {
		if(!empty($addl["val"])) $this->append($addl, $id);
		if(!empty($rmvl)) $this->remove($rmvl, $id);
	}
	
	/**
	* Append documents
	* Append documents associated to that area
	* 
	* @access public
	* @param array $addl Documents to be appended
	* @param string $id ID of area
	*/
	public function append($addl, $id) {
		# Iterate through each document
		foreach($addl['val'] as $i => $title) {
			if(empty($title)) continue;
			
			$ins = '';
			
			# Append using document ID
			if(!empty($addl['id'][$i])) {
				$ins = "INSERT INTO {$this->table} VALUES ('{$id}', '{$addl['id'][$i]}', '1', '{$this->user['id']}', '".date('Y-m-d H:i:s:ms')."')";
			}
			# Doc id is not found
			else {
				# Search document
				$res = $this->mysqli->query("SELECT ID FROM Documents WHERE Title='{$title}'");
				
				# Document is found
				if($res and !empty($res->num_rows)) {
					$obj = $res->fetch_object();
					$ins = "INSERT INTO {$this->table} VALUES ('{$id}', '{$obj->ID}', '1', '{$this->user['id']}', '".date('Y-m-d H:i:s:ms')."')";
				}
			}
			
			# Append document
			if(!empty($ins)) {
				if(!$this->mysqli->query($ins)) {
					$this->notif[] = "ERROR: ins area-doc {$id} $title.<br/>";
				}
			}
		}
	}
	
	/**
	* Remove documents
	* Remove documents associated to that area
	* 
	* @access public
	* @param array $rmvl Documents to be removed
	* @param string $id ID of area
	*/
	public function remove($rmvl, $id) {
		$del = "DELETE FROM {$this->table} WHERE PID='{$id}' AND CID IN ('".implode("', '", $rmvl)."')";
		
		# Remove documents
		if(!$this->mysqli->query($del)) {
			$this->notif[] = "ERROR: rem micro<br/>";
		}
	}
	
	/**
	* Fetch documents
	* Fetch documents associated with an area
	* 
	* @access public
	* @param string $id ID of area
	* @param int $start Start of return results
	*/
	public function fetch($id, $start) {
		# Project sections
		if($this->area=='proj-sec') {
			$sel = "
				SELECT T1.* FROM Documents AS T1 INNER JOIN {$this->table} AS T2
					ON T1.ID=T2.DocID AND T2.CID='{$id}' ORDER BY T2.CrtOn LIMIT {$start}, 10
			";
		}
		# Other areas
		else {
			$sel = "
				SELECT T1.* FROM Documents AS T1 INNER JOIN {$this->table} AS T2
					ON T1.ID=T2.CID AND T2.PID='{$id}' ORDER BY T2.CrtOn LIMIT {$start}, 10
			";
		}
		
		$res = $this->mysqli->query($sel);
		
		# List all documents
		if($res and !empty($res->num_rows)) {
			while($doc = $res->fetch_object()) { ?>
				<li class="doc">
					<a href="main.php?doc=view&id=<?php echo $doc->ID ?>" data-tool="{'head':'<?php echo $doc->Title ?>','x':'l'}"><?php echo Tool::truncate($doc->Title, 80) ?></a>
					<button class="locked small" data-title="<?php echo $doc->Title ?>" data-doc="<?php echo $doc->Path ?>">Open</button>
					<button type="button" class="remove icon read" data-area="doc" data-id="<?php echo $doc->ID ?>"></button>
				</li> <?php
			}
		}
	}
	
	/**
	* Retrieve details
	* Get all details associated with document to be displayed
	* 
	* @access private
	* @param string $area Area where document is associated
	* @param string $id ID of document
	* 
	* @return mixed Returned results on search
	*/
	private function retrieve($area, $id) {
		$selSize = "SELECT FOUND_ROWS()";
		
		switch($area) {
			# Microorganisms
			case 'micro':
				$sel = "
					SELECT SQL_CALC_FOUND_ROWS DISTINCT T1.* FROM Microorganisms AS T1 INNER JOIN MicroDocs AS T2
						ON T1.ID=T2.PID AND T2.CID='{$id}' AND T1.Remove='0' ORDER BY T2.CrtOn LIMIT 10
				";
			break;
			
			# Projects
			case 'proj':
				$sel = "
					SELECT SQL_CALC_FOUND_ROWS DISTINCT T1.* FROM Projects AS T1 INNER JOIN ProjDocs AS T2
						ON T1.ID=T2.PID AND T2.CID='{$id}' AND T1.Remove='0' ORDER BY T2.CrtOn LIMIT 10
				";
			break;
			
			# Resources
			case 'rsrc':
				$sel = "
					SELECT SQL_CALC_FOUND_ROWS DISTINCT T1.* FROM Resources AS T1 INNER JOIN DocRsrcs AS T2
						ON T1.ID=T2.CID AND T2.PID='{$id}' AND T1.Remove='0' ORDER BY T2.CrtOn LIMIT 10
				";
			break;
		}
		
		# Find in database
		$res = $this->mysqli->query($sel);
		$size = $this->mysqli->query($selSize);
		$size = $size->fetch_row();
		
		# Return results and size
		return array($res, $size[0]);
	}
	
	/**
	* Display all documents
	* Retrieve all contents of documents on a page
	* 
	* @access public
	* @param array $queries IDs of documents
	*/
	public function displayAll($queries, $opts) { ?>
		<output> <?php
			if($results = $this->search($queries, $opts, 0, 10)) {
				while($result = $results[0]->fetch_object()) {
					$this->displayContent($result, false);
				}
			} ?>
		</output> <?php
	}
	
	/**
	* Guess document
	* Provides a list of documents (guess) on user input
	* Makes selection of document and id faster
	* 
	* @access public
	*/
	public function guess($query) {
		# Search for documents matching the query string and constrains passed
		$docs = $this->search($query, $_REQUEST, 0, 10);
		
		# Document is not found
		if(!$docs or empty($docs[1])) {
			return false;
		}
		
		# List all found documents
		while($doc = $docs[0]->fetch_object()) { ?>
			<div class="guess doc" data-id="<?php echo $doc->ID ?>" data-value="<?php echo $doc->Title ?>" tabindex="0"
				<?php if(strlen($doc->Title) > 50) { ?> data-tool="{'head':'<?php echo $doc->Title ?>'}" <?php } ?>>
				<a href="main.php?doc=view&id=<?php echo $doc->ID ?>"> <?php
					echo Tool::truncate($doc->Title, 50); ?></a>
			</div> <?php
		}
		
		if($_REQUEST['s']=='true') { ?>
			<div class="guess-header doc query">
				<a href="main.php?doc=view&q=<?php echo urlencode($query) ?>" target="_blank" title="<?php echo $query ?>"><?php echo Tool::truncate($query, 30) ?></a>
				<span class="right bold none" title="<?php echo ($found = $docs[0]->num_rows.' of '.$docs[1]).' items found' ?>"><?php echo $found ?></span>
			</div> <?php
		}
	}
	
	/**
	* Display main document stage
	* List all documents in the main page
	* 
	* @access public
	* @param mixed $docs List of documents from returned search results
	* @param integer $size Size of rows from returned search results
	* @param string $query Query string that was searched for
	* @param array $opts Optional parameters
	* @param integer $start Starting row in mysql returned results
	*/
	public function displayMain($docs, $size, $query, $opts, $start) {
		# One document to be viewed
		$view = $docs->num_rows==1;
		# Page number
		$page = ceil(($start+1)/10);
		# Process URL params
		$optstr = Tool::optstrify($opts); ?>
		
		<div id="side">
			<div id="navis"> <?php
				# Links to previous ten items ?>
				<a href="main.php?<?php echo $optstr.(empty($query) ? '' : '&q='.$query).(empty($start) ? '&s=0' : '&s='.(intval($start)-10)) ?>"
					class="navi ui ui-button prev <?php if(empty($start)) echo 'disabled' ?>" tabindex="-1" title="Previous 10 items"></a> <?php
				# Links to next ten items ?>
				<a href="main.php?<?php echo $optstr.(empty($start) ? '&s=10' : '&s='.(intval($start)+10)) ?>"
					class="navi ui ui-button next <?php if(($docs->num_rows<10) or ($docs->num_rows*$page)>=$size) { echo 'disabled'; } ?>" tabindex="-1" title="Next 10 items"></a>
			</div> <?php
			
			# Knobs to stage document ?>
			<div id="knobs"> <?php $i = 1;
				while($doc = $docs->fetch_object()) {
					# Contains data query title, id, tool (tooltip help)
					$title = Tool::truncate($trtitle = $doc->Title, 80); ?>
					<div id="knob<?php echo $doc->ID ?>" class="knob doc <?php if($view) echo "lock" ?>"
						data-query="<?php echo $doc->ID ?>" data-id="<?php echo $doc->ID ?>" data-tool="{'head':'<b class=\'cool\'><?php echo $title ?></b>','x':'l'}">
						<?php echo $i++ ?> </div> <?php
				} ?>
			</div>
		</div> <?php
		
		# Labels stage items ?>
		<div id="hnotif" class="escape"> <?php
			# Shows metadata of all searched items ?>
			<span id="query" class="escape iblock" data-tool="{'head':'<?php echo ($all = (empty($query) and empty($opts['q']))) ? "All documents" : (empty($opts['q']) ? $trtitle : $opts['q']) ?>','x':'l'}"
				<?php if(!($nctrl = empty($_COOKIE['ctrl']['search']))) { echo 'style="width:400px"'; } ?>>
				<?php echo ($all ? "All documents" : ($view ? $title : $query)) ?>
			</span>
			
			<span>
				<span id="search-ctrls" <?php if($nctrl) { echo 'class="none"'; } ?>> <?php
					# No. of returned results
					echo '<span id="numresults">Showing '.($docs->num_rows).' of <b>'.$size.'</b> result(s)</span> on page ';
					
					# Many microorganisms are to be viewed
					$ob = isset($_REQUEST['ob']); $of = true;
					unset($opts['ob']); unset($opts['oa']);
					$optstr = Tool::optstrify($opts);
					
					# Prepare filter options and page selector ?>
					<select id="main-page" class="page navi" data-tool="{'head':'Page'}"> <?php
						for($i=0, $x=$size/10; $i<$x; $i++)	echo "<option ".((isset($opts['s']) and $opts['s']==($i*10)) ? 'selected="selected"' : '').'value="main.php?'.$optstr.(empty($query) ? '' : '&q='.$query).'&s='.($i*10).'">'.($i+1).'</option>';?>
					</select> sorted by <?php
					
					# Prepare filter options ?>
					<select class="navi" data-tool="{'head':'Sort'}">
						<option value="main.php?<?php echo $optstr ?>&ob=title&oa=asc" <?php if($ob and $_REQUEST['ob']=='title') { echo 'selected="selected"'; $of = false; } ?>>Title</option>
						<option value="main.php?<?php echo $optstr ?>&ob=notes&oa=asc" <?php if($ob and $_REQUEST['ob']=='notes') { echo 'selected="selected"'; $of = false; } ?>>Notes</option>
						<option value="main.php?<?php echo $optstr ?>&ob=crtby&oa=asc" <?php if($ob and $_REQUEST['ob']=='crtby') { echo 'selected="selected"'; $of = false; } ?>>Author</option>
						<option value="main.php?<?php echo $optstr ?>&ob=updon&oa=desc" <?php if($ob and $_REQUEST['ob']=='updon') { echo 'selected="selected"'; $of = false; } ?>>Last edited</option>
						<option value="main.php?<?php echo $optstr ?>&ob=shron&oa=desc" <?php if($ob and $_REQUEST['ob']=='shron') { echo 'selected="selected"'; $of = false; } ?>>Last shared</option>
						<option value="main.php?<?php echo $optstr ?>&ob=crton&oa=desc" <?php if($ob and $_REQUEST['ob']=='crton') { echo 'selected="selected"'; $of = false; } ?>>Date created</option>
						<option value="main.php?<?php echo $optstr ?>&ob=id&oa=asc" <?php if($ob and $_REQUEST['ob']=='id') { echo 'selected="selected"'; $of = false; } ?>>ID</option>
					</select>
				</span>
				<span <?php if(!$nctrl) { echo 'class="none"'; } ?>><?php echo "$docs->num_rows of <b>$size</b> result(s) on page <b>$page</b>";  ?></span> <button type="button" class="navi-details <?php echo (!$nctrl ? 'selected' : '') ?>" data-tool="{'head':'Search controls'}"></button>
			</span>
		</div> <?php
		
		# Contains all document headers ?>
		<div id="stage"> <?php
			# Reset pointer to first row in mysql result
			$docs->data_seek(0);
			
			# List all images on its own entry pages
			while($doc = $docs->fetch_object()) {
				# Show first the heading of each document
				$this->displayHeading($doc, $view);
			} ?>
		</div> <?php
	}
	
	/**
	* Display a document heading
	* Displays a heading for each document in the results
	* which contains the document's title
	* 
	* @access public
	* @param mixed $doc Contains all details of the document
	* @param boolean $cont Checks if content is to be displayed too
	*/
	public function displayHeading($doc, $cont) {
		# List an document first as an area with a header that can be selected/clicked by the user in the stage
		# Data included: head (title), id (document id)
		?> <div id="area<?php echo $doc->ID ?>" class="stage area doc" data-head="<?php echo $doc->Title ?>">
			<div class="div-header doc <?php echo $cont ? "active lock" : "heading" ?>" data-id="<?php echo $doc->ID ?>" data-content="doc"
				<?php if(strlen($doc->Title)>100) echo 'data-tool="{\'head\':\''.$doc->Title.'\',\'x\':\'l\'}"' ?>>
				<a href="main.php?doc=view&id=<?php echo $doc->ID ?>" class="title" tabindex="-1">
					<?php echo Tool::truncate($doc->Title, 100) ?></a>
			</div> <?php
			
			# Show document's contents if necessary
			if($cont) {
				$this->displayContent($doc, $cont);
			} ?>
		</div> <?php
	}
	
	/**
	* Display contents of document
	* Displays the contents of a document, from its title
	* to its associated items in other areas of the system
	* 
	* @access public
	* @param mixed $doc Contains all details of the document
	* @param boolean $cont Checks if only one document is found in results
	*/
	public function displayContent($doc, $cont) {
		?> <div class="div-content">
			<form id="form-doc<?php echo $doc->ID ?>" class="doc" name="form-doc" method="post" action="process.php?doc=edit" enctype="multipart/form-data" novalidate="novalidate">
			<div class="div-upper">
				<div class="div-body">
					<div class="div-peel title"><b>Title</b></span></div>
					<div class="div-case">
						<textarea name="title" class="title reqd read" readonly="readonly" rows="<?php echo ceil(strlen($doc->Title)/80) ?>"><?php echo $doc->Title ?></textarea>
					</div>
					
					<div class="div-peel peel <?php echo ($flag = (empty($doc->Abstr) or $doc->Abstr=='NULL')) ? "on" : "off open" ?> next notes"><b>Abstract</b>
					</div>
					<div class="div-case <?php if($flag) echo "none" ?>">
						<textarea name="abstr" rows="<?php echo empty($doc->Abstr) ? '5' : ceil(strlen($doc->Abstr)/100) ?>" class="read abled" readonly="readonly"><?php echo $doc->Abstr ?></textarea>
					</div> <?php
					
					//PROJECTS//////////////////////////////////////////////////////////////////////////////////////////////////////////////
					
					list($resProj, $sizeProj) = $this->retrieve('proj', $doc->ID); ?>
					
					<div class="div-peel peel <?php echo ($empty = empty($sizeProj)) ? "on" : "off open" ?> next proj">
						<b>Projects</b> <span><?php echo $sizeProj ?></span>
					</div>
					<div class="div-case <?php if($empty) echo "none" ?>">
						<ol> <?php
							if(!$empty) {
								while($proj = $resProj->fetch_object()) { ?>
									<li class="proj">
										<a href="main.php?proj=view&id=<?php echo $proj->ID ?>"><?php echo $proj->Title ?></a>
									</li> <?php
								}
							} ?>
						</ol>
					</div> <?php
					
					//MICROORGANISMS//////////////////////////////////////////////////////////////////////////////////////////////////////////////
					
					list($resMicro, $sizeMicro) = $this->retrieve('micro', $doc->ID); ?>
					
					<div class="div-peel peel <?php echo ($empty = empty($sizeMicro)) ? "on" : "off open" ?> next micro">
						<b>Microorganisms</b> <span><?php echo $sizeMicro ?></span>
					</div>
					<div class="div-case <?php if($sizeMicro <= 0) echo "none" ?>">
						<ol> <?php
							if(!$empty) { $i = 1;
								while($micro = $resMicro->fetch_object()) { ?>
									<li class="micro">
										<a href="main.php?micro=view&id=<?php echo $micro->ID ?>"><i> <?php
											echo $micro->Name ?></i></a>
										<button type="button" class="remove icon read" data-area="micro" data-id="<?php echo $micro->ID ?>"></button>
									</li> <?php
								}
							} ?>
						</ol>
						<a class="fetch micro tick" data-area="doc" data-id="<?php echo $doc->ID ?>" data-start="10">Show more</a>
						
						<div class="none">
							<div class="default">
								<input type="text" class="micro" name="micro[val][]" placeholder="Scientific name" data-guess="micro=guess" data-name="micro[]"/>
								<button class="append icon" type="button" data-area="micro" data-id="0"></button>
								<input type="hidden" name="micro[id][]" class="abled"/>
							</div>
							<div class="micros"></div>
						</div>
						
						<button type="button" class="addmore peel on prev read" data-on="Add" data-off="Cancel">Add</button>
					</div> <?php
					
					//RESOURCES//////////////////////////////////////////////////////////////////////////////////////////////////////////////
					
					list($resRsrc, $sizeRsrc) = $this->retrieve('rsrc', $doc->ID); ?>
					
					<div class="div-peel peel <?php echo ($empty = empty($sizeRsrc)) ? "on" : "off open" ?> next rsrc">
						<b>Resources</b> <span><?php echo $sizeRsrc ?></span>
					</div>
					<div class="div-case <?php if($empty) echo "none" ?>"> <?php
						if(!$empty) { ?>
							<ol> <?php
								while($rsrc = $resRsrc->fetch_object()) { ?>
									<li class="rsrc">
										<a href="main.php?rsrc=view&id=<?php echo $rsrc->ID ?>"><?php echo $rsrc->Title ?></a>
										<button type="button" class="remove icon read" data-area="rsrc" data-id="<?php echo $rsrc->ID ?>"></button>
									</li> <?php
								} ?>
							</ol>
							<a class="fetch rsrc tick" data-area="doc" data-id="<?php echo $doc->ID ?>" data-start="10">Show more</a> <?php
						} ?>
						
						<div class="none">
							<div class="default">
								<input type="text" class="rsrc" name="rsrc[val][]" placeholder="Resource title" data-guess="rsrc=guess"/>
								<button class="append icon" type="button" data-area="rsrc" data-id="0"></button>
								<input type="hidden" name="rsrc[id][]" class="abled"/>
							</div>
							<div class="rsrcs"></div>
						</div>
						
						<button type="button" class="addmore peel on prev read" data-on="Add" data-off="Cancel">Add</button>
					</div>
					
					<div class="div-peel peel <?php echo ($empty = (empty($doc->Ref) or $doc->Ref=='NULL')) ? "on" : "off open" ?> next ref">
						<b>References</b></div>
					<div class="div-case <?php if($empty) echo "none" ?>">
						<textarea name="ref" rows="<?php echo $empty ? '3' : ceil(strlen($doc->Ref)/100) ?>" class="read abled" readonly="readonly"> <?php
							echo $doc->Ref ?></textarea>
					</div> <?php
					
					//INPUT////////////////////////////////////////////////////////////////////////////////////////////////////////////// ?>
					
					<div class="div-peel peel on next file none"><b>Update</b></div>
					<div class="div-case file none">
						<input name="input[]" type="file" class="file" accept="application/json"/>
					</div> <?php
					
					//SETTINGS////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ ?>
					
					<div class="div-peel peel on next safe none"><b>Settings</b><span class="setting help"></span></div>
					<div class="div-case none safe"></div>
				</div>
				
				<div class="div-head">
					<div class="controls"> <?php
						if(!empty($doc->Path)) { ?>
							<button class="open doc dial" type="button" data-title="<?php echo Tool::truncate($doc->Title, 80) ?>" data-doc="<?php echo $doc->Path ?>"><span>Open</span></button><hr/> <?php
						} ?>
						
						<button class="share dial" data-area="doc" data-id="<?php echo $doc->ID ?>" type="button"><span>Share</span></button> <?php
						
						$sett = new Setting('doc', null, $this->mysqli, $this->user);
						$verified = $sett->verify($doc->ID) and in_array($this->user['type'], array('PRIME','ADMIN'));
							
						if($doc->Categ=='BSC' or $verified) { ?>
							<a href="process.php?doc=get&id=<?php echo $doc->ID ?>"><span class="dload dial button"><span>Download</span></span></a> <?php
						} ?><hr/>
						
						<button class="details dial" type="button" data-area="doc" data-id="<?php echo $doc->ID ?>" data-name="<?php echo $doc->Title ?>"><span>Details</span></button>
						
						<button class="stat dial peel on next" type="button"><b>Contents</b></button>
						<ul class="metas none">
							<li class="meta">Projects <span><?php echo $sizeProj ?></span></li>
							<li class="meta">Microorganisms <span><?php echo $sizeMicro ?></span></li>
							<li class="meta">Resources <span><?php echo $sizeRsrc ?></span></li>
						</ul> <?php
						
						if($verified) { ?><hr/>
							<button class="edit dial" data-area="doc" data-id="<?php echo $doc->ID ?>" type="reset"><span>Edit</span></button> <?php
						} ?>
					</div>
				</div>
				
				<div class="div-mind">
					<input name="id" type="hidden" class="id abled" value="<?php echo $doc->ID ?>"/>
					<input name="upd" type="checkbox" class="abled none" value="<?php echo $doc->ID ?>"/>
					<input name="del" type="checkbox" class="del abled none" value="<?php echo $doc->ID ?>"/>
					<input name="recov" type="checkbox" class="recov abled" value="<?php echo $doc->ID ?>"/>
					<input name="path" type="hidden" class="del abled none" value="<?php echo $doc->Path ?>"/>
				</div>
			</div>
			
			<div class="div-dial"> <?php
				if($doc->Remove=='0') { ?>
					<button class="delete tick read left" type="button" form="form-doc<?php echo $doc->ID ?>" data-area="doc">Delete</button> <?php
				}
				else { ?>
					<button class="recover tick read left" type="button" form="form-doc<?php echo $doc->ID ?>" data-area="doc">Recover</button> <?php
				} ?>
				<button type="button" form="form-doc<?php echo $doc->ID ?>" class="cancel edit read">Cancel</button>
				<button type="submit" class="read">Update</button> <?php
				
				if(!$cont) { ?>
					<button type="button" class="close-content reset">Close</button> <?php
				} ?>
			</div>
			</form> </div> <?php
	}
}
?>